package com.abeir.bilibili.convert;

import com.abeir.bilibili.convert.deprecated.VideoAudioScanner;
import com.abeir.bilibili.utils.Sundry;

import java.io.*;
import java.nio.file.Path;
import java.util.Optional;

public class DefaultConvertFactory implements ConvertFactory<FfmpegMerger, File> {

    private String titleFilename = "videoInfo.json";
    private String playurlFilename = ".playurl";
    private String mediaSuffix = ".m4s";
    private String[] videoFilenameSuffixes;
    private String[] audioFilenameSuffixes;

    private final Path dir;

    public DefaultConvertFactory(Path dir) {
        this.dir = dir;
    }

    public void setTitleFilename(String titleFilename) {
        if (titleFilename != null && !titleFilename.isEmpty()) {
            this.titleFilename = titleFilename;
        }
    }

    public void setPlayurlFilename(String playurlFilename) {
        if (playurlFilename != null && !playurlFilename.isEmpty()) {
            this.playurlFilename = playurlFilename;
        }
    }

    public void setMediaSuffix(String mediaSuffix) {
        if (mediaSuffix != null && !mediaSuffix.isEmpty()) {
            this.mediaSuffix = mediaSuffix;
        }
    }

    public void setVideoFilenameSuffixes(String[] suffixes) {
        if(suffixes != null && suffixes.length > 0) {
            videoFilenameSuffixes = suffixes;
        }
    }

    public void setAudioFilenameSuffixes(String[] suffixes) {
        if(suffixes != null && suffixes.length > 0) {
            audioFilenameSuffixes = suffixes;
        }
    }

    @Override
    public Optional<File> convert(FfmpegMerger merger) throws Exception {
        String title = processTitle();
        title = Sundry.safeFilename(title);

        try(RandomAccessFile videoStream = processVideo(); RandomAccessFile audioStream = processAudio()) {
            return merger.merge(videoStream, audioStream, title);
        }
    }

    private String processTitle() throws IOException {
        TitleScanner titleScanner = new TitleScanner(titleFilename);
        Optional<File> titleFile = titleScanner.target(this.dir);
        if (titleFile.isEmpty()) {
            throw new FileNotFoundException("not found title: " + titleFilename);
        }

        TitleParser titleParser = new TitleParser();
        Optional<TitleInfo> titleInfo = titleParser.parse(titleFile.get());
        if(titleInfo.isEmpty()){
            throw new InvalidObjectException("title is empty");
        }

        TitleConverter titleConverter = new TitleConverter();
        return titleConverter.convert(titleInfo.get());
    }

    private RandomAccessFile processVideo() throws Exception {
        Optional<File> videoFile;
        if(videoFilenameSuffixes != null && videoFilenameSuffixes.length > 0) {
            VideoAudioScanner videoScanner = new VideoAudioScanner(videoFilenameSuffixes);
            videoFile = videoScanner.target(this.dir);
        }else{
            VideoScanner videoScanner = new VideoScanner(this.playurlFilename, this.mediaSuffix);
            videoFile = videoScanner.target(this.dir);
        }
        if (videoFile.isEmpty()) {
            throw new FileNotFoundException("not found video in dir: " + this.dir);
        }

        BinParser binParser = new BinParser();
        RandomAccessFile origin = binParser.parse(videoFile.get());

        VideoAudioConverter videoAudioConverter = new VideoAudioConverter();
        return videoAudioConverter.convert(origin);
    }

    private RandomAccessFile processAudio() throws Exception {
        Optional<File> audioFile;
        if(audioFilenameSuffixes != null && audioFilenameSuffixes.length > 0) {
            VideoAudioScanner audioScanner = new VideoAudioScanner(audioFilenameSuffixes);
            audioFile = audioScanner.target(this.dir);
        }else{
            AudioScanner audioScanner = new AudioScanner(this.playurlFilename, this.mediaSuffix);
            audioFile = audioScanner.target(this.dir);
        }
        if (audioFile.isEmpty()) {
            throw new FileNotFoundException("not found audio in dir: " + this.dir);
        }

        BinParser binParser = new BinParser();
        RandomAccessFile origin = binParser.parse(audioFile.get());

        VideoAudioConverter videoAudioConverter = new VideoAudioConverter();
        return videoAudioConverter.convert(origin);
    }
}
